package site.wtcc.originalfavor.func.config;

import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.*;
import java.io.IOException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * okhttp配置
 *
 * @author hexiaodou
 * @date 2022/09/14 15:43:51
 */
@Configuration
public class OkHttpConfig {
    @Value("${ok.http.connect-timeout:10}")
    private Integer connectTimeout;

    @Value("${ok.http.read-timeout:5}")
    private Integer readTimeout;

    @Value("${ok.http.write-timeout:5}")
    private Integer writeTimeout;

    @Value("${ok.http.max-idle-connections:200}")
    private Integer maxIdleConnections;

    @Value("${ok.http.keep-alive-duration:1}")
    private Long keepAliveDuration;

    //@Bean(name = "restTemplate")
    //public RestTemplate restTemplate() {
    //	ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient());
    //	RestTemplate restTemplate = new RestTemplate(factory);
    //	restTemplate.getMessageConverters()
    //			.set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
    //	return restTemplate;
    //}

    //获取这个SSLSocketFactory
    public static SSLSocketFactory getSSLSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, getTrustManager(), new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //获取TrustManager
    private static TrustManager[] getTrustManager() {
        return new TrustManager[] {
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[] {};
                }
            }
        };
    }

    //获取HostnameVerifier
    public static HostnameVerifier getHostnameVerifier() {
        return (s, sslSession) -> true;
    }

    public static X509TrustManager getX509TrustManager() {
        X509TrustManager trustManager = null;
        try {
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init((KeyStore)null);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
                throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
            }
            trustManager = (X509TrustManager)trustManagers[0];
        } catch (Exception e) {
            e.printStackTrace();
        }

        return trustManager;
    }

    @Bean
    public OkHttpClient okHttpClient() throws Exception {

        final OkHttpClient okHttpClient;
        OkHttpClient.Builder builder = new OkHttpClient.Builder().connectionPool(pool())
            .readTimeout(readTimeout, TimeUnit.SECONDS)
            .connectTimeout(connectTimeout, TimeUnit.SECONDS)
            .writeTimeout(writeTimeout, TimeUnit.SECONDS)
            .sslSocketFactory(getSSLSocketFactory(), getX509TrustManager())
            .hostnameVerifier(getHostnameVerifier()).addInterceptor(new HeaderInterceptor());
        builder.getDispatcher$okhttp().setMaxRequestsPerHost(200);
        builder.getDispatcher$okhttp().setMaxRequests(200);
        okHttpClient = builder.build();
        return okHttpClient;
    }

    private ConnectionPool pool() {
        return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.MINUTES);
    }

    class HeaderInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request().newBuilder()
                .addHeader("Connection", "keep-alive")
                .build();
            Response response = chain.proceed(request);
            return response;
        }
    }

}
